In [1]:
%load_ext autoreload
%autoreload 2
from import_src import *

from collections import OrderedDict

# TODO: import the portfolio for a single source

large_us_stocks = OrderedDict({"VTI": 0.8, "VNQ (REIT)": 0.2})

large_exus_stocks = OrderedDict({"EAFE": 1.0})

small_us_stocks = OrderedDict({"IJS": 1.0})

small_exus_stocks = OrderedDict({"EAFE Small-Cap": 1.0})

bonds = OrderedDict({"BND": 1.0})

fund_shares = [large_us_stocks, large_exus_stocks, small_us_stocks, small_exus_stocks, bonds]

Variate portfolio by Stock/Bond ratio¶

In [2]:
from src.domain import *
from src.distribution import create_distributions_from
from src.display.distribution import display_distributions

default_distribution = SharesDistribution(
    categories=SharesCategoriesDistribution(
        by_type=dict(zip((ShareType.Stock, ShareType.Bond), (0.75, 0.25))),
        by_region=dict(zip((Region.US, Region.ExUS), (0.7, 0.3))),
        by_cap=dict(zip((Cap.Large, Cap.Small), (0.7, 0.3))),
        by_term=dict(zip((Term.Long,), (1,))),
    ),
    shares=[FundsDistribution(x) for x in fund_shares],
)


def modify_distrib_by_type_ratio(distrib: SharesDistribution, stock_rate: float):
    if distrib.categories:
        bond_rate = 1 - stock_rate
        distrib.categories.by_type[ShareType.Stock] = stock_rate
        distrib.categories.by_type[ShareType.Bond] = bond_rate


distributions_rates = [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1]
distributions_names = [f"{round(x * 100)}/{round((1 - x) * 100)}" for x in distributions_rates]
distributions = create_distributions_from(default_distribution, modify_distrib_by_type_ratio, distributions_rates)

display_distributions(distributions, names=distributions_names)
0/100 10/90 20/80 30/70 40/60 50/50 60/40 70/30 80/20 90/10 100/0
VTI 0.0% 3.92% 7.84% 11.76% 15.68% 19.6% 23.52% 27.44% 31.36% 35.28% 39.2%
VNQ (REIT) 0.0% 0.98% 1.96% 2.94% 3.92% 4.9% 5.88% 6.86% 7.84% 8.82% 9.8%
EAFE 0.0% 2.1% 4.2% 6.3% 8.4% 10.5% 12.6% 14.7% 16.8% 18.9% 21.0%
IJS 0.0% 2.1% 4.2% 6.3% 8.4% 10.5% 12.6% 14.7% 16.8% 18.9% 21.0%
EAFE Small-Cap 0.0% 0.9% 1.8% 2.7% 3.6% 4.5% 5.4% 6.3% 7.2% 8.1% 9.0%
BND 100.0% 90.0% 80.0% 70.0% 60.0% 50.0% 40.0% 30.0% 20.0% 10.0% 0.0%
Mean ret. Std
0/100 5.12 3.69
10/90 5.69 3.71
20/80 6.24 4.29
30/70 6.77 5.25
40/60 7.27 6.41
50/50 7.76 7.70
60/40 8.22 9.04
70/30 8.66 10.43
80/20 9.08 11.85
90/10 9.47 13.28
100/0 9.84 14.72

Variate portfolio by Cap size ratio¶

In [3]:
from src.domain import *
from src.distribution import create_distributions_from
from src.display.distribution import display_distributions

default_distribution = SharesDistribution(
    categories=SharesCategoriesDistribution(
        by_type=dict(zip((ShareType.Stock, ShareType.Bond), (1, 0))),
        by_region=dict(zip((Region.US, Region.ExUS), (0.7, 0.3))),
        by_cap=dict(zip((Cap.Large, Cap.Small), (0.7, 0.3))),
        by_term=dict(zip((Term.Long,), (1,))),
    ),
    shares=[FundsDistribution(x) for x in fund_shares],
)


def modify_distrib_by_cap_ratio(distrib: SharesDistribution, large_cap: float):
    if distrib.categories:
        small_cap = 1 - large_cap
        distrib.categories.by_cap[Cap.Large] = large_cap
        distrib.categories.by_cap[Cap.Small] = small_cap


distributions_rates = [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1]
distributions_names = [f"{round(x * 100)}/{round((1 - x) * 100)}" for x in distributions_rates]
distributions = create_distributions_from(default_distribution, modify_distrib_by_cap_ratio, distributions_rates)

display_distributions(distributions, names=distributions_names)
0/100 10/90 20/80 30/70 40/60 50/50 60/40 70/30 80/20 90/10 100/0
VTI 0.0% 5.6% 11.2% 16.8% 22.4% 28.0% 33.6% 39.2% 44.8% 50.4% 56.0%
VNQ (REIT) 0.0% 1.4% 2.8% 4.2% 5.6% 7.0% 8.4% 9.8% 11.2% 12.6% 14.0%
EAFE 0.0% 3.0% 6.0% 9.0% 12.0% 15.0% 18.0% 21.0% 24.0% 27.0% 30.0%
IJS 70.0% 63.0% 56.0% 49.0% 42.0% 35.0% 28.0% 21.0% 14.0% 7.0% 0.0%
EAFE Small-Cap 30.0% 27.0% 24.0% 21.0% 18.0% 15.0% 12.0% 9.0% 6.0% 3.0% 0.0%
BND 0.0% 0.0% 0.0% 0.0% 0.0% 0.0% 0.0% 0.0% 0.0% 0.0% 0.0%
Mean ret. Std
0/100 10.96 16.83
10/90 10.82 16.45
20/80 10.67 16.09
30/70 10.52 15.76
40/60 10.35 15.46
50/50 10.19 15.18
60/40 10.01 14.94
70/30 9.84 14.72
80/20 9.65 14.55
90/10 9.46 14.40
100/0 9.27 14.30

Variate portfolio by Region ratio¶

In [4]:
from src.domain import *
from src.distribution import create_distributions_from
from src.display.distribution import display_distributions

default_distribution = SharesDistribution(
    categories=SharesCategoriesDistribution(
        by_type=dict(zip((ShareType.Stock, ShareType.Bond), (1, 0))),
        by_region=dict(zip((Region.US, Region.ExUS), (0.7, 0.3))),
        by_cap=dict(zip((Cap.Large, Cap.Small), (0.7, 0.3))),
        by_term=dict(zip((Term.Long,), (1,))),
    ),
    shares=[FundsDistribution(x) for x in fund_shares],
)


def modify_distrib_by_region_ratio(distrib: SharesDistribution, us_rate: float):
    if distrib.categories:
        exUs_rate = 1 - us_rate
        distrib.categories.by_region[Region.US] = us_rate
        distrib.categories.by_region[Region.ExUS] = exUs_rate


distributions_rates = [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1]
distributions_names = [f"{round(x * 100)}/{round((1 - x) * 100)}" for x in distributions_rates]
distributions = create_distributions_from(default_distribution, modify_distrib_by_region_ratio, distributions_rates)

display_distributions(distributions, names=distributions_names)
0/100 10/90 20/80 30/70 40/60 50/50 60/40 70/30 80/20 90/10 100/0
VTI 0.0% 5.6% 11.2% 16.8% 22.4% 28.0% 33.6% 39.2% 44.8% 50.4% 56.0%
VNQ (REIT) 0.0% 1.4% 2.8% 4.2% 5.6% 7.0% 8.4% 9.8% 11.2% 12.6% 14.0%
EAFE 70.0% 63.0% 56.0% 49.0% 42.0% 35.0% 28.0% 21.0% 14.0% 7.0% 0.0%
IJS 0.0% 3.0% 6.0% 9.0% 12.0% 15.0% 18.0% 21.0% 24.0% 27.0% 30.0%
EAFE Small-Cap 30.0% 27.0% 24.0% 21.0% 18.0% 15.0% 12.0% 9.0% 6.0% 3.0% 0.0%
BND 0.0% 0.0% 0.0% 0.0% 0.0% 0.0% 0.0% 0.0% 0.0% 0.0% 0.0%
Mean ret. Std
0/100 6.17 15.87
10/90 6.72 15.53
20/80 7.26 15.25
30/70 7.79 15.02
40/60 8.31 14.85
50/50 8.83 14.74
60/40 9.34 14.70
70/30 9.84 14.72
80/20 10.33 14.81
90/10 10.81 14.96
100/0 11.29 15.17